package org.NooLab.tikaserver.tcp.agents;

import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;

import org.NooLab.structures.texx.plugg.algo.intf.AlgoReaderIntf;
import org.NooLab.structures.texx.plugg.algo.intf.AlgoSourceDescription;
import org.NooLab.structures.texx.plugg.algo.intf.AlgorithmParameter;
import org.NooLab.structures.texx.plugg.algo.intf.AlgorithmParameters;
 
 
import org.NooLab.texxplugg.tika.TikaReader;
import org.NooLab.tikaserver.TikaServerFactory;
import org.NooLab.tikaserver.intf.TikaSrvDataTransferPkgIntf;
import org.NooLab.tikaserver.tcp.agents.TikaServerAgent.MessageReceiver;
import org.NooLab.utilities.logging.LogControl;
import org.NooLab.utilities.logging.PrintLog;
import org.apache.commons.collections.BidiMap;
import org.apache.commons.collections.bidimap.DualHashBidiMap;

import com.cybozu.labs.langdetect.Detector;
import com.cybozu.labs.langdetect.DetectorFactory;
import com.cybozu.labs.langdetect.LangDetectException;




public class TextProducer extends Observable implements Runnable{

	
	int datatype;
	String filename;
	String guid;
	
	TikaServerFactory srvFactory;
	TikaServerAgent srvAgent;
	TikaSrvDataTransferPkgIntf data ;
	
	Thread txtpThrd;
	
	PrintLog out = new PrintLog(2,true);
	
	private String receipt="";
	private String rawPlainText="";
	private String sourceUrl="";
	
	
	// ========================================================================
	public TextProducer(TikaServerFactory factory, TikaServerAgent serverAgent) {
		// TikaSrvDataTransferPkgIntf._TRANSFER_DATA_TYPE_LOCALFILE
	
		srvFactory = factory;
		
		TikaSrvDataTransferPkgIntf data = new TikaSrvDataTransferPkg();
		
		this.datatype = data.getTypeOfData() ;
		this.filename = data .getFilename();
		this.guid = data.getGuid() ;
		
		
		txtpThrd = new Thread(this,"txtpThrd");
		txtpThrd.start();
	}
	
	public TextProducer(TikaServerFactory factory,  TikaServerAgent srvAgent, TikaSrvDataTransferPkgIntf data) {  
		
		this.data = data;
		srvFactory = factory;
		
		this.srvAgent = srvAgent;
		
		this.datatype = data.getTypeOfData() ;
		this.filename = data .getFilename();
		this.guid = data.getGuid() ;
		
		txtpThrd = new Thread(this,"txtpThrd");
		txtpThrd.start();

	}
	// ========================================================================
	
	public void close(){

		try {
			
			txtpThrd.join();
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	private void produce() throws Exception{
		
		// extract text
											out.print(2, "TikaServer, producing & extracting... <<< "+ filename);
											// out.delay(6000) ;
		
		
											
		importData( filename, 0) ;
		
		// data.setResultText("eins zwei drei...");
		
		// dependent on request, we return raw-plain or an XML 
		data.setResultText( rawPlainText ) ;
		
											out.printErr(2, "TikaServer, found text is L = "+rawPlainText.length() ) ;
		out.delay(250);
		data.setConfirmationCode( TikaSrvDataTransferPkgIntf._TRANSFER_CONFIRMATION_COMPLETED ) ;
		
		
		srvAgent.senderDevice.send( srvAgent.sob.encode(data), data.getGuid());
		
		 
	}

	// ========================================================================
	
	
	protected void importData( String filename, int iflag) throws Exception{
		
		TikaReader reader;
		BidiMap resultType = new DualHashBidiMap();
		
		
		// 
		try {
			
			reader = TikaReader.class.newInstance();
			
			ArrayList<Object> algorithmparams = new ArrayList<Object>();
			
			resultType.put("result", srvFactory.getResultType());
			algorithmparams.add(resultType);
			
			reader.setParameters(algorithmparams) ;
			
			rawPlainText = readDocument(filename,(AlgoReaderIntf)reader);
			// this might not be "plain text", it ight be an XML !!
			// yet, TikaReader does not care about that, it just has to pass the request!
			
			
		} catch (InstantiationException e) {
			
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			
			e.printStackTrace();
		}
		
	}

	private String readDocument( String filename, AlgoReaderIntf reader) throws LangDetectException {
		 
		Long calctimestart = System.currentTimeMillis() ;
		String urlstring="",version="";

		try {

			AlgoSourceDescription sourceDescription = new AlgoSourceDescription();

			urlstring = filename;

			sourceDescription.setUrlstring(urlstring);
			calctimestart = System.currentTimeMillis();
			
			receipt = reader.setDataDescription(sourceDescription);
			/*
			 * // Logger.getRootLogger().setLevel(Level.INFO);
			 * Logger.getRootLogger().setLevel(Level.ERROR); Logger lgg =
			 * Logger.getLogger("org.NooLab.texxplugg");
			 * LogControl.cLogger.setLogging( "org.apache.tika" );
			 * LogControl.cLogger.setLogging( "org.NooLab.texxplugg" );
			 * 
			 * 
			 * lgg = Logger.getRootLogger(); lgg.setLevel(Level.ERROR);
			 * 
			 * lgg.removeAllAppenders() ;
			 */
						out.print(2, "starting extracting cores ...");
			reader.calculate(); 
			// we need a progress indicator ... and several docs in parallel ...
			// and not output to console ...
			version = reader.getVersion();

			boolean hb = false;

			hb = reader.performPostProcessing();
			
		} catch (Exception e) {
			// java.lang.AbstractMethodError ???
			if (LogControl.Level >= 2) {
				e.printStackTrace();
			}
		}
						out.print(2, "going to read the document via reader-plugin (6)...");
		rawPlainText = reader.getText();
		// note that "rawPlainText" could contain an XML, which also contains MetaData about the document !!
		
		String mimeType = reader.getDocTypeMime(); // either mime (Tika) or extension or similar
		
		
		if (rawPlainText.trim().indexOf("<?xml")>=0){
			
			Detector detector = DetectorFactory.create(); 
			String detectionText = rawPlainText; if (detectionText.length()>2000){detectionText = detectionText.substring(0,1999);}
			detector.append( detectionText );
			String langCode = detector.detect();
			langCode = srvFactory.getISO3166Code(langCode);
			
			// insert mime source
			String str ="";
			
			str =       "   <mime value=\""+mimeType+"\" /> \n   ";
			str = str + "   <language code=\""+langCode+"\" /> \n   ";
			str = str + "   <source url=\""+urlstring+"\" />";

			str = "<metadata>\n" + str;
			rawPlainText = rawPlainText.replace("<metadata>", str);
		}
		
		long calctimefinish = System.currentTimeMillis();
		long calctime = calctimefinish - calctimestart;

		sourceUrl = urlstring;
		long timestamp = System.currentTimeMillis();

		if ((rawPlainText.length() > 100) && (calctime > 1)) { // CONSTANT
																// minimum
																// length ...

			// postprocessing: concatenate hyphenated words
			// numbers in the text: footnotes/endnotes dunne point out.15... using POI
			// create a document which creates the context

						out.print(3, "document read via reader-plugin (6.A), length is approx. " + 
									  rawPlainText.length()+ " chars ...");

		} else {
						out.print(2, "going to read the document via reader-plugin (6.B)...");
						out.print(2, "document was too short (<100 characters)");

			rawPlainText = "";
			sourceUrl = "";
			timestamp = 0L;
		}

		if (reader != null) {
			reader.clear();
			reader = null;
		}

		return rawPlainText;
	}

	// ========================================================================
	
	
	@Override
	public void run() {

		try {
			
			produce();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		out.delay(1000);
		data = null;
		rawPlainText = "";

	}
	
	
}
